/**
 * Copyright 2011 Joe Choi, All rights reserved.
 */
package tao.data.structure.tree;

/**
 * The TaoTree is design as a Facade for manipulating the tree and its operation
 * 
 * @author Joe Choi
 * @version 1.0.0
 */
public class TaoTree {
	/**
	 * Create a tree without children node
	 */
	public static <V> Tree<V> tree(V value) {
		return(new ConcreteTree<V>(value));
	}
	
	/**
	 * Create a tree with subtree
	 */
	public static <V> Tree<V> tree(V value, Tree<V>... subtree) {
		return(new ConcreteTree<V>(value, subtree));
	}
	
	/**
	 * Create a tree by copying the content of given tree
	 */
	public static <V> Tree<V> tree(Tree<V> tree) {
		return(new ConcreteTree<V>(tree));
	}
	
	/**
	 * Create a growable tree
	 */
	public static <V> GrowableTree<V> gTree(V value) {
		return(new ConcreteGrowableTree<V>(value));
	}
	
	/**
	 * Create a growable tree with subtree 
	 */
	public static <V> GrowableTree<V> gTree(V value, GrowableTree<V>... subtree) {
		return(new ConcreteGrowableTree<V>(value, subtree));
	}
	
	/**
	 * Create a Traversal for a tree with specific traversing order
	 * <br>
	 * <b>Note that if created Traversal is In-Order, then the factor is zero by default.
	 * To create an In-Order Traversal with specific factor, using the method 
	 * <code> createTraversal(Tree<T> tree, TravelOrder order, int factor) </code> instead </b>
	 * 
	 * @see Traversal.Order
	 * @see Traversal
	 */
	public static <V> Traversal<V> createTraversal(Tree<V> tree, Traversal.Order order) {
		return(createTraversal(tree, order, 0));
	}
	
	/**
	 * Create a Traversal for a tree with specific traversing order
	 * 
	 * @param factor is only meaningful to In-Order Traversal
	 * @see Traversal.Order
	 * @see Traversal
	 */
	public static <V> Traversal<V> createTraversal(Tree<V> tree, Traversal.Order order, int factor) {
		return(determineTraversal(tree, order, factor).create());
	}
	
	private static <V> Traversal.Factory<V> determineTraversal(Tree<V> tree, Traversal.Order order, int factor) {
		switch(order) {
			case Pre: 	return(new PreOrderTraversal.Factory<V>(tree));
			case Post: 	return(new PostOrderTraversal.Factory<V>(tree));
			case In: 	return(new InOrderTraversal.Factory<V>(tree, factor));
			default: 	throw new UnsupportedOperationException("Unknown traversal: " + order);
		}		
	}
}